package com.ruoyi.asms.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.ruoyi.ams.controller.AmsAssetInfoController;
import com.ruoyi.ams.controller.AmsAssetTypeController;
import com.ruoyi.ams.controller.AmsOwnAddressController;
import com.ruoyi.ams.domain.vo.DoImportAddressInfoVo;
import com.ruoyi.ams.domain.vo.ImportAddressVo;
import com.ruoyi.ams.domain.vo.SaveAmsAssetInfoBatchVo;
import com.ruoyi.asms.domain.*;
import com.ruoyi.asms.domain.vo.AddressAndDeptInfoVo;
import com.ruoyi.asms.domain.vo.AsmsMaintenanceAssetAddVo;
import com.ruoyi.asms.domain.vo.AssetFullInfoImportVo;
import com.ruoyi.asms.domain.vo.DispatchVo;
import com.ruoyi.common.core.domain.AsmsAssetFullInfo;
import com.ruoyi.common.core.domain.AssetInfoView;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.*;
import com.ruoyi.common.core.domain.vo.DeptUserVo;
import com.ruoyi.common.core.domain.vo.DoImportAssetInfoVo;
import com.ruoyi.common.core.domain.vo.DoImportDeptUserInfoVo;
import com.ruoyi.common.core.domain.vo.ImportDeptUserInfoVo;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.security.service.TokensService;
import com.ruoyi.file.controller.SysFileController;
import com.ruoyi.system.controller.SysDeptController;
import com.ruoyi.system.controller.SysUserController;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
public class AsmsReusingService {


    @Autowired
    private IAsmsFaultService asmsFaultService;
    @Autowired
    private IAsmsFaultAssetService asmsFaultAssetService;
    @Autowired
    private IAsmsFaultReportStageService asmsFaultReportStageService;
    @Autowired
    private IAsmsFaultDispatchStageService asmsFaultDispatchStageService;
    @Autowired
    private IAsmsFaultConfirmStageService asmsFaultConfirmStageService;
    @Autowired
    private IAsmsFaultFeedbackStageService asmsFaultFeedbackStageService;
    @Autowired
    private IAsmsFaultAssetReasonService asmsFaultAssetReasonService;
    @Autowired
    private IAsmsMaintenanceChargeInfoService asmsMaintenanceChargeInfoService;
    @Autowired
    private IAsmsMaintenanceAssetService asmsMaintenanceAssetService;
    @Autowired
    private IAsmsAssetFullInfoService asmsAssetFullInfoService;
    @Autowired
    private IAsmsFaultResolveStageService asmsFaultResolveStageService;
    @Autowired
    private IAsmsOwnChargeInfoService asmsOwnChargeInfoService;
    @Autowired
    private TokensService tokenService;

    @Autowired
    private IFaultInfoViewService faultInfoViewService;

    @Autowired
    private AsyncService asyncService;
    @Autowired
    private AsmsReusingService asmsReusingService;

    @Autowired
    private IAsmsOwnMaintenanceDeptService asmsOwnMaintenanceDeptService;
    @Autowired
    private IAsmsOwnAddressAssetCodeService asmsOwnAddressAssetCodeService;

//    @Autowired
//    private RemoteDeptService remoteDeptService;
//    @Autowired
//    private RemoteAssetInfoService remoteAssetInfoService;
//    @Autowired
//    private RemoteFileService remoteFileService;
//    @Autowired
//    private RemoteAssetTypeService remoteAssetTypeService;
//    @Autowired
//    private RemoteUserService remoteUserService;
//    @Autowired
//    private RemoteAssetAddressService remoteAssetAddressService;
    @Autowired
    private SysDeptController deptController;
    @Autowired
    private AmsAssetInfoController assetInfoController;
    @Autowired
    private SysFileController sysFileController;
    @Autowired
    private AmsAssetTypeController assetTypeController;
    @Autowired
    private SysUserController userController;
    @Autowired
    private AmsOwnAddressController ownAddressController;
    @Autowired
    ExecutorService executorService;

    public String getAmsUserName() {

        String userName = assetInfoController.getAmsUserName();
        return userName;
    }

    public AsmsAssetFullInfo setAssetInfo(AsmsMaintenanceAssetAddVo asmsMaintenanceAssetAddVo){
        AsmsAssetFullInfo asmsAssetFullInfo = new AsmsAssetFullInfo();
        BeanUtils.copyProperties(asmsMaintenanceAssetAddVo,asmsAssetFullInfo);
        R<SysDept> sysDept = deptController.getDeptById(asmsMaintenanceAssetAddVo.getMaintenanceDeptId());
        if (sysDept.getCode() == R.FAIL){
            throw new ServiceException(sysDept.getMsg());
        }
        asmsAssetFullInfo.setMParentId(sysDept.getData().getParentId());
        asmsAssetFullInfo.setMAncestors(sysDept.getData().getAncestors());
        asmsAssetFullInfo.setMDeptShortName(sysDept.getData().getDeptShortName());
        asmsAssetFullInfo.setMDeptFullName(sysDept.getData().getDeptFullName());
        asmsAssetFullInfo.setMLeader(sysDept.getData().getLeader());
        asmsAssetFullInfo.setMPhone(sysDept.getData().getPhone());
        asmsAssetFullInfo.setMEmail(sysDept.getData().getEmail());
        return asmsAssetFullInfo;
    }

    /**
     *
     * @param startNumber 起始码
     * @param number 生成的码数量
     * @return
     */
    @Transactional(rollbackFor ={WxErrorException.class})
    public AjaxResult createWxMaCode(Integer startNumber, Integer number) throws WxErrorException {

        return AjaxResult.success();
    }

    public void dispatch(DispatchVo dispatchVo) {
        SysUser repair = dispatchVo.getRepair();
        SysUser finder = dispatchVo.getFinder();
        String faultAddress = dispatchVo.getFaultAddress();
        String faultDescription = dispatchVo.getFaultDescription();
        Long faultTime = dispatchVo.getFaultTime();
        String assetTypeName = dispatchVo.getAssetTypeName();
        Long faultAssetId = dispatchVo.getFaultAssetId();

        AsmsFaultAsset faultAsset = asmsFaultAssetService.getById(dispatchVo.getFaultAssetId());

        asmsFaultDispatchStageService.update(new UpdateWrapper<AsmsFaultDispatchStage>()
                .set(AsmsFaultDispatchStage.END_TIME, System.currentTimeMillis())
                .set(AsmsFaultDispatchStage.MAINTENANCE_CHARGE_USER_ID, SecurityUtils.getUserId())
                .set(AsmsFaultDispatchStage.STATUS, 1)
                .eq(AsmsFaultDispatchStage.FAULT_ASSET_ID, faultAssetId)
        );

        AsmsFaultResolveStage one = asmsFaultResolveStageService.getOne(new QueryWrapper<AsmsFaultResolveStage>()
                .eq(AsmsFaultResolveStage.FAULT_ASSET_ID, faultAssetId), false);
        if (one != null) {
            one.setFaultResolveUserId(repair.getUserId());
            one.setMaintenanceDeptId(repair.getDeptId());
            asmsFaultResolveStageService.updateById(one);
        } else {
            AsmsFaultResolveStage resolveStage = new AsmsFaultResolveStage();
            resolveStage.setFaultAssetId(faultAssetId);
            resolveStage.setStartTime(System.currentTimeMillis());
            if (Objects.nonNull(repair)) {
                resolveStage.setFaultResolveUserId(repair.getUserId());
                resolveStage.setMaintenanceDeptId(repair.getDeptId());
            }
            resolveStage.setStatus(0);
            asmsFaultResolveStageService.save(resolveStage);
        }

        //派单后将故障所属阶段推进到故障处理阶段
        asmsFaultAssetService.update(new UpdateWrapper<AsmsFaultAsset>()
                .set(AsmsFaultAsset.STAGE, 3).set(AsmsFaultAsset.FAULT_RESOLVE_USER_ID, repair.getUserId())
                .eq(AsmsFaultAsset.FAULT_ASSET_ID, faultAssetId));

        //发送微信通知
        asyncService.sendDispatchWxSubscribeMsg(repair, finder, faultDescription, faultAddress, faultTime, assetTypeName,
                faultAssetId,faultAsset.getDescriptionImages(), 0);
        try{
            Integer faultId = Integer.valueOf(faultAsset.getRemark());
            asyncService.sendDispatchToOldPlatform("",dispatchVo.getRepair().getNickName(),faultId);
        }catch(Exception ignored){
        }
    }
    /**
     * 获取当前部门能看到的故障数据
     */
    public List<FaultInfoView> getUserCanLookFaultList(Long startTime, Long endTime) {
        QueryWrapper<FaultInfoView> wrapper = new QueryWrapper<>();
        if (startTime != null && endTime != null) {
            wrapper.ge(FaultInfoView.CREATE_TIME, startTime).le(FaultInfoView.CREATE_TIME, endTime);
        }
        if (!SysUser.isAdmin(SecurityUtils.getUserId())) {
            Set<Long> userMaintenanceDeptIds = tokenService.getUserMaintenanceDeptIds();
            if (userMaintenanceDeptIds.size() > 0) {
                wrapper.in(FaultInfoView.MAINTENANCE_DEPT_ID, userMaintenanceDeptIds);
            } else {
                return new ArrayList<>();
            }
        }
        return faultInfoViewService.list(wrapper);
    }

    public FaultFullInfoVo getFaultFullInfo(Long faultAssetId) {

        FaultFullInfoVo infoVo = new FaultFullInfoVo();

        FaultInfoView faultInfoView = faultInfoViewService.getOne(new QueryWrapper<FaultInfoView>()
                .eq(FaultInfoView.FAULT_ASSET_ID, faultAssetId), false);

        AsmsAssetFullInfo assetFullInfo = asmsAssetFullInfoService.getOne(new QueryWrapper<AsmsAssetFullInfo>()
                .eq(AsmsAssetFullInfo.ASSET_ID, faultInfoView.getAssetId()), false);

        FaultUserAddressAssetInfo faultUserAddressAssetInfo = new FaultUserAddressAssetInfo();

        if (faultInfoView.getAddressId() != null) {
            R<AmsOwnAddress> addressInfo = ownAddressController.getInfoR(faultInfoView.getAddressId());
            if (addressInfo.getCode() == R.FAIL) {
                throw new ServiceException(addressInfo.getMsg());
            }
            if (addressInfo.getData() != null)
                BeanUtils.copyProperties(addressInfo.getData(), faultUserAddressAssetInfo);
        }

        BeanUtils.copyProperties(assetFullInfo, faultUserAddressAssetInfo);
        if (faultInfoView.getFaultFindUserId() != null) {
            R<SysUser> user = userController.getUserByIdR(faultInfoView.getFaultFindUserId());
            if (user.getCode() == R.FAIL) {
                throw new ServiceException(user.getMsg());
            }
            if (user.getData() != null)
                BeanUtils.copyProperties(user.getData(), faultUserAddressAssetInfo);
        }
        faultUserAddressAssetInfo.setFullName(assetFullInfo.getOwnDeptName()+faultUserAddressAssetInfo.getFullName());
        BeanUtils.copyProperties(faultInfoView, faultUserAddressAssetInfo);
        infoVo.setBasicInfo(faultUserAddressAssetInfo);
        if (faultInfoView.getStage() >= 1) {
            ReportStageInfoVo reportStageInfoVo = new ReportStageInfoVo();
            AsmsFaultReportStage reportStage = asmsFaultReportStageService.getOne(new QueryWrapper<AsmsFaultReportStage>()
                    .eq(AsmsFaultReportStage.FAULT_ASSET_ID, faultAssetId), false);
            if (reportStage != null)
                BeanUtils.copyProperties(reportStage, reportStageInfoVo);

            if (faultInfoView.getOwnDeptId() != null) {
                R<SysDept> rSysDept = deptController.getDeptById(faultInfoView.getOwnDeptId());
                if (rSysDept.getCode() == R.FAIL) {
                    throw new ServiceException(rSysDept.getMsg());
                }
                reportStageInfoVo.setOwnChargeDeptName(rSysDept.getData().getDeptFullName());
            }

            if (reportStage != null && reportStage.getOwnChargeUserId() != null) {
                R<SysUser> rSysUser = userController.getUserByIdR(reportStage.getOwnChargeUserId());
                if (rSysUser.getCode() == R.FAIL) {
                    throw new ServiceException(rSysUser.getMsg());
                }
                if(rSysUser.getData()==null){
                    reportStageInfoVo.setOwnChargeUserName("未知");
                    reportStageInfoVo.setOwnChargeUserPhone("未知");
                }else {
                    reportStageInfoVo.setOwnChargeUserName(rSysUser.getData().getNickName());
                    reportStageInfoVo.setOwnChargeUserPhone(rSysUser.getData().getPhonenumber());
                }
            }
            infoVo.setReportStage(reportStageInfoVo);
        }
        if (faultInfoView.getStage() >= 2) {
            DispatchStageInfoVo dispatchStageInfoVo = new DispatchStageInfoVo();
            AsmsFaultDispatchStage dispatchStage = asmsFaultDispatchStageService.getOne(new QueryWrapper<AsmsFaultDispatchStage>().eq(AsmsFaultDispatchStage.FAULT_ASSET_ID, faultAssetId), false);
            if (dispatchStage != null)
                BeanUtils.copyProperties(dispatchStage, dispatchStageInfoVo);

            if (dispatchStage != null && dispatchStage.getStatus() == 1) {

                R<SysDept> rSysDept = deptController.getDeptById(dispatchStage.getMaintenanceDeptId());
                if (rSysDept.getCode() == R.FAIL) {
                    throw new ServiceException(rSysDept.getMsg());
                }
                dispatchStageInfoVo.setMaintenanceDeptName(rSysDept.getData().getDeptFullName());

                R<SysUser> rSysUser = userController.getUserByIdR(dispatchStage.getMaintenanceChargeUserId());
                if (rSysUser.getCode() == R.FAIL) {
                    throw new ServiceException(rSysUser.getMsg());
                }
                if(rSysUser.getData()!=null){
                    dispatchStageInfoVo.setMaintenanceChargeUserName(rSysUser.getData().getNickName());
                    dispatchStageInfoVo.setMaintenanceChargeUserPhone(rSysUser.getData().getPhonenumber());
                }else {
                    dispatchStageInfoVo.setMaintenanceChargeUserName("");
                    dispatchStageInfoVo.setMaintenanceChargeUserPhone("");
                }
                infoVo.setDispatchStage(dispatchStageInfoVo);
            }
        }
        if (faultInfoView.getStage() >= 3) {
            ResolveStageInfoVo resolveStageInfoVo = new ResolveStageInfoVo();
            AsmsFaultResolveStage resolveStage = asmsFaultResolveStageService.getOne(new QueryWrapper<AsmsFaultResolveStage>()
                    .eq(AsmsFaultResolveStage.FAULT_ASSET_ID, faultAssetId).ne(AsmsFaultResolveStage.STATUS, -2), false);
            R<SysUser> rSysUser = new R<>();
            if (resolveStage != null) {
                BeanUtils.copyProperties(resolveStage, resolveStageInfoVo);
                rSysUser = userController.getUserByIdR(resolveStage.getFaultResolveUserId());
            }
            if (rSysUser.getCode() == R.FAIL) {
                throw new ServiceException(rSysUser.getMsg());
            }
            if(rSysUser.getData()!=null){
                resolveStageInfoVo.setFaultResolveUserName(rSysUser.getData().getNickName());
                resolveStageInfoVo.setFaultResolveUserPhone(rSysUser.getData().getPhonenumber());
            }else {
                resolveStageInfoVo.setFaultResolveUserName("");
                resolveStageInfoVo.setFaultResolveUserPhone("");
            }
            infoVo.setResolveStage(resolveStageInfoVo);
        }
        if (faultInfoView.getStage() >= 4) {
            ConfirmStageInfoVo confirmStageInfoVo = new ConfirmStageInfoVo();
            AsmsFaultConfirmStage confirmStage = asmsFaultConfirmStageService.getOne(new QueryWrapper<AsmsFaultConfirmStage>().eq(AsmsFaultConfirmStage.FAULT_ASSET_ID, faultAssetId), false);
            if (confirmStage != null)
                BeanUtils.copyProperties(confirmStage, confirmStageInfoVo);
            infoVo.setConfirmStage(confirmStageInfoVo);
        }
        return infoVo;
    }


    @Transactional
    public AjaxResult importAddressAndDeptInfo(List<AddressAndDeptInfoVo> list){

        List<ImportAddressVo> addressVos = new ArrayList<>();
        Map<String, Object> deptFullMap = new HashMap<>();
        Map<String, Object> deptMap = new HashMap<>();
        for (AddressAndDeptInfoVo vo : list ){

            if (StringUtils.isEmpty(vo.getUDeptFullName())) {
                return AjaxResult.error("资产使用部门不可为空！");
            }

            if (StringUtils.isEmpty(vo.getAddressNameNo1())) {
                return AjaxResult.error("资产一级位置不可为空！");
            }


            if(deptFullMap.get(vo.getUDeptFullName())== null){
                List<SysDept> uDepts = deptController.getDeptByFullName(vo.getUDeptFullName()).getData();
                if(uDepts == null){
                    return AjaxResult.error("remoteDeptService 调用失败");
                }
                if(uDepts.size() == 0){
                    return AjaxResult.error("存在未导入的部门");
                }
                deptFullMap.put(vo.getUDeptFullName(),uDepts.get(0));
                deptMap.put(uDepts.get(0).getDeptShortName(),uDepts.get(0));

            }



            ImportAddressVo addressVo = new ImportAddressVo();
            BeanUtils.copyProperties(vo, addressVo);
            StringBuilder fullAddress = new StringBuilder();
            if (StringUtils.isNotEmpty(vo.getAddressNameNo1())) {
                fullAddress.append(vo.getAddressNameNo1());
                if (StringUtils.isNotEmpty(vo.getAddressNameNo2())) {
                    fullAddress.append(vo.getAddressNameNo2());
                    addressVo.setAddressNameNo2Full(fullAddress.toString());
                    if (StringUtils.isNotEmpty(vo.getAddressNameNo3())) {
                        fullAddress.append(vo.getAddressNameNo3());
                        addressVo.setAddressNameNo3Full(fullAddress.toString());
                        if (StringUtils.isNotEmpty(vo.getAddressNameNo4())) {
                            fullAddress.append(vo.getAddressNameNo4());
                            addressVo.setAddressNameNo4Full(fullAddress.toString());
                            if (StringUtils.isNotEmpty(vo.getAddressNameNo5())) {
                                fullAddress.append(vo.getAddressNameNo5());

                            }
                        }
                    }
                }
            }
            addressVo.setFullAddress(fullAddress.toString());
            SysDept dept = (SysDept)deptFullMap.get(vo.getUDeptFullName());

            addressVo.setUDeptShortName(dept.getDeptShortName());
            addressVos.add(addressVo);

        }

        DoImportAddressInfoVo addressInfoVo = new DoImportAddressInfoVo();
        addressInfoVo.setAddressVos(addressVos);
        addressInfoVo.setDeptMap(deptMap);
        R<Map<String, AmsOwnAddress>> mapR = ownAddressController.importAddressInfo(
                addressInfoVo, "");


        Set<String> deptNameSet = deptMap.keySet();
        List<AsmsOwnMaintenanceDept> asmsOwnMaintenanceDeptList = new LinkedList<>();
        for(String deptName : deptNameSet){
            AsmsOwnMaintenanceDept asmsOwnMaintenanceDept = new AsmsOwnMaintenanceDept();
            SysDept sysDept = (SysDept)deptMap.get(deptName);
            asmsOwnMaintenanceDept.setOwnDeptId(sysDept.getDeptId());
            asmsOwnMaintenanceDept.setMaintenanceDeptId(tokenService.getLoginUser().getDeptid());
            asmsOwnMaintenanceDept.setCreateBy(tokenService.getLoginUser().getUsername());
            asmsOwnMaintenanceDept.setCreateTime(System.currentTimeMillis());
            List<AsmsOwnMaintenanceDept> list1 = asmsOwnMaintenanceDeptService.list(new QueryWrapper<AsmsOwnMaintenanceDept>().
                    eq(AsmsOwnMaintenanceDept.OWN_DEPT_ID, sysDept.getDeptId()).eq(AsmsOwnMaintenanceDept.MAINTENANCE_DEPT_ID, tokenService.getLoginUser().getDeptid()));
            if(list1 == null || list1.size() == 0){
                asmsOwnMaintenanceDeptList.add(asmsOwnMaintenanceDept);
            }
        }

       asmsOwnMaintenanceDeptService.saveBatch(asmsOwnMaintenanceDeptList);

        return AjaxResult.success();
    }


    @Transactional
    public AjaxResult importAssetInfo(List<AssetFullInfoImportVo> list){
        //数据预检查
        List<FullTypeInfoVo> assetTypeAndTemplateSet = new ArrayList<>();
        Set<String> typeSet = new HashSet<>();
        //Set<String> deptSet = new HashSet<>();
        Set<String> assetBrandSet = new HashSet<>();
        Set<String> assetProjectSet = new HashSet<>();
        List<DeptUserVo> deptuserList = new ArrayList<>();
        Set<String> codeSet = new HashSet<>();
        Set<String> addressSet = new HashSet<>();
        List<ImportAddressVo> addressVos = new ArrayList<>();
        int codeNumber = 0;
        Set<String> addressCodes = new HashSet<>();
        for (AssetFullInfoImportVo vo : list) {
            if (StringUtils.isEmpty(vo.getAssetTypeName())) {
                return AjaxResult.error("资产名称不可为空！");
            }
            if (StringUtils.isEmpty(vo.getAssetTemplateName())) {
                return AjaxResult.error("资产型号不可为空！");
            }
            if (StringUtils.isEmpty(vo.getODeptShortName())) {
                return AjaxResult.error("资产所属部门不可为空！");
            }
            if (StringUtils.isEmpty(vo.getUDeptShortName())) {
                return AjaxResult.error("资产使用部门不可为空！");
            }
            if (StringUtils.isEmpty(vo.getAddressNameNo1())) {
                return AjaxResult.error("资产一级位置不可为空！");
            }
            if (StringUtils.isEmpty(vo.getMDeptShortName())) {
                return AjaxResult.error("资产维护商或部门不可为空！");
            }
            addressCodes.add(vo.getAddressCode());
            FullTypeInfoVo fullTypeInfoVo = new FullTypeInfoVo();
            typeSet.add(vo.getAssetTypeName());
            fullTypeInfoVo.setAssetTypeName(vo.getAssetTypeName());
            if (StringUtils.isNotEmpty(vo.getAssetTemplateName())) {
                fullTypeInfoVo.setTemplateName(vo.getAssetTemplateName());
            }
            if (StringUtils.isNotEmpty(vo.getSpecification())) {
                fullTypeInfoVo.setSpecification(vo.getSpecification());
            }
            if (StringUtils.isNotEmpty(vo.getMeasureUnit())) {
                fullTypeInfoVo.setMeasureUnit(vo.getMeasureUnit());
            }
            assetTypeAndTemplateSet.add(fullTypeInfoVo);
            vo.setFullTypeInfoVo(fullTypeInfoVo);
            if (StringUtils.isNotEmpty(vo.getBrandName())) {
                assetBrandSet.add(vo.getBrandName());
            }
            if (StringUtils.isNotEmpty(vo.getProjectName())) {
                assetProjectSet.add(vo.getProjectName());
            }
            if (StringUtils.isNotEmpty(vo.getSn())) {
                codeNumber++;
                codeSet.add(vo.getSn());
            }
            vo.setIndex(list.indexOf(vo));
            DeptUserVo deptUserVo = new DeptUserVo();
            deptUserVo.setUDeptName(vo.getUDeptShortName());
            if (StringUtils.isNotEmpty(vo.getNickName())) {
                deptUserVo.setNickName(vo.getNickName());
            }
            if (StringUtils.isNotEmpty(vo.getPhonenumber())) {
                deptUserVo.setCellphone(vo.getPhonenumber());
            }
            deptUserVo.setMDeptName(vo.getMDeptShortName());
            deptUserVo.setODeptName(vo.getODeptShortName());
            deptuserList.add(deptUserVo);

            ImportAddressVo addressVo = new ImportAddressVo();
            BeanUtils.copyProperties(vo, addressVo);
            StringBuilder fullAddress = new StringBuilder();
            if (StringUtils.isNotEmpty(vo.getAddressNameNo1())) {

                fullAddress.append(vo.getAddressNameNo1());

                if (StringUtils.isNotEmpty(vo.getAddressNameNo2())) {

                    fullAddress.append(vo.getAddressNameNo2());
                    addressVo.setAddressNameNo2Full(fullAddress.toString());

                    if (StringUtils.isNotEmpty(vo.getAddressNameNo3())) {

                        fullAddress.append(vo.getAddressNameNo3());
                        addressVo.setAddressNameNo3Full(fullAddress.toString());

                        if (StringUtils.isNotEmpty(vo.getAddressNameNo4())) {

                            fullAddress.append(vo.getAddressNameNo4());
                            addressVo.setAddressNameNo4Full(fullAddress.toString());

                            if (StringUtils.isNotEmpty(vo.getAddressNameNo5())) {
                                fullAddress.append(vo.getAddressNameNo5());
                            }
                        }
                    }
                }
            }
            addressVo.setFullAddress(fullAddress.toString());
            vo.setFullAddress(fullAddress.toString());
            addressVos.add(addressVo);
            vo.setStartUseTime(DateUtils.stringToLong(vo.getStartUseTimeString(), "yyyy年MM月dd日"));
            vo.setEndUseTime(DateUtils.stringToLong(vo.getEndUseTimeString(), "yyyy年MM月dd日"));
        }
        if (codeSet.size() != codeNumber) {
            //excel中存在重复编码
            return AjaxResult.error("资产编码存在重复，请排除！");
        }


        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        RequestContextHolder.setRequestAttributes(servletRequestAttributes, true);

        //数据检查
        CompletableFuture<Map<String, AsmsOwnAddressAssetCode>> addressCodesCheckTask = CompletableFuture.supplyAsync(() -> {
            Map<String, AsmsOwnAddressAssetCode> resultMap =new HashMap<>();
            if (addressCodes.size() > 0) {
                List<AsmsOwnAddressAssetCode> list1 = asmsOwnAddressAssetCodeService.list(new QueryWrapper<AsmsOwnAddressAssetCode>().in(AsmsOwnAddressAssetCode.CODE, addressCodes));
                list1.forEach(item->resultMap.put(item.getCode(),item));
                //                if (addressCodeInfo.size() > 0) {
//                    for (AsmsOwnAddressAssetCode code : addressCodeInfo) {
//                        usedCodes.add(code.getCode());
//                    }
            }
            return resultMap;

        });
        CompletableFuture<R<Map<String, AmsAssetType>>> assetInfoCheckTask = CompletableFuture.supplyAsync(() -> {
            return assetInfoController.assetInfoCheckTypeAndCode(
                    typeSet,
                    codeSet);
        });

        CompletableFuture<R<Map<String, Object>>> deptInfoCheckTask = CompletableFuture.supplyAsync(() -> {
            return deptController.deptCheckByDeptNamesAndLoginUserDeptId(
                    deptuserList);
        });
        Map<String, AmsAssetType> typeMap = new HashMap<>();
        Map<String, Object> deptMap = new HashMap<>();
        try {
            CompletableFuture.allOf(assetInfoCheckTask, deptInfoCheckTask,addressCodesCheckTask).get();
            StringBuilder stringBuilder = new StringBuilder();
            boolean success = true;
            if (R.FAIL == assetInfoCheckTask.get().getCode()) {
                stringBuilder.append(assetInfoCheckTask.get().getMsg());
                success = false;
            }
            if (R.FAIL == deptInfoCheckTask.get().getCode()) {
                stringBuilder.append("\n").append(deptInfoCheckTask.get().getMsg());
                success = false;
            }
//            if(addressCodesCheckTask.get().size()>0){
//                success = false;
//                stringBuilder.append("\n");
//                stringBuilder.append("以下位置码已使用，请排查并更换：");
//                for (String addressCode : addressCodesCheckTask.get()) {
//                    stringBuilder.append("\n");
//                    stringBuilder.append(addressCode);
//                }
//            }
            if (!success) {
                return AjaxResult.error(stringBuilder.toString());
            }
            typeMap = assetInfoCheckTask.get().getData();
            deptMap = deptInfoCheckTask.get().getData();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        //基础数据录入
        DoImportDeptUserInfoVo deptUserInfoVo = new DoImportDeptUserInfoVo();
        deptUserInfoVo.setDeptMap(deptMap);
        deptUserInfoVo.setDeptUserList(deptuserList);

//        CompletableFuture<R<ImportDeptUserInfoVo>> importUserInfoTask = CompletableFuture.supplyAsync(() -> {
//            return userController.doImportDeptUserInfo(
//                    deptUserInfoVo,"");
//        });
        DoImportAssetInfoVo assetInfoVo = new DoImportAssetInfoVo();
        assetInfoVo.setBrandNames(assetBrandSet);
        assetInfoVo.setProjectNames(assetProjectSet);
        assetInfoVo.setTypeNames(assetTypeAndTemplateSet);
        assetInfoVo.setTypeMap(typeMap);
//        CompletableFuture<R<ImportAssetInfoVo>> importAssetInfoTask = CompletableFuture.supplyAsync(() -> {
//            return assetInfoController.importAssetInfo(
//                    assetInfoVo,"");
//        });
        DoImportAddressInfoVo addressInfoVo = new DoImportAddressInfoVo();
        addressInfoVo.setAddressVos(addressVos);
        addressInfoVo.setDeptMap(deptMap);
//        CompletableFuture<R<Map<String, AmsOwnAddress>>> importAddressInfoTask = CompletableFuture.supplyAsync(() -> {
//            return ownAddressController.importAddressInfo(
//                    addressInfoVo,"");
//        });
        ImportAssetInfoVo importAssetInfoVo = null;
        ImportDeptUserInfoVo importDeptUserInfoVo = null;
        Map<String, AmsOwnAddress> addressVoMap = null;
 //       try {
          //  CompletableFuture.allOf(importUserInfoTask).get();
           // R<ImportDeptUserInfoVo> importDeptUserInfoVoR = importUserInfoTask.get();
            R<ImportDeptUserInfoVo> importDeptUserInfoVoR =userController.doImportDeptUserInfo(
                    deptUserInfoVo,"");
           // R<ImportAssetInfoVo> importAssetInfoVoR = importAssetInfoTask.get();
            R<ImportAssetInfoVo> importAssetInfoVoR = assetInfoController.importAssetInfo(
                    assetInfoVo,"");
           // R<Map<String, AmsOwnAddress>> importAddressVoTask = importAddressInfoTask.get();
            R<Map<String, AmsOwnAddress>> importAddressVoTask =ownAddressController.importAddressInfo(
                    addressInfoVo,"");
            if (R.FAIL == importAddressVoTask.getCode()) {
                throw new ServiceException(importAddressVoTask.getMsg());
            }
            if (R.FAIL == importAssetInfoVoR.getCode()) {
                throw new ServiceException(importAssetInfoVoR.getMsg());
            }
            if (R.FAIL == importDeptUserInfoVoR.getCode()) {
                throw new ServiceException(importDeptUserInfoVoR.getMsg());
            }
            importAssetInfoVo = importAssetInfoVoR.getData();
            importDeptUserInfoVo = importDeptUserInfoVoR.getData();
            addressVoMap = importAddressVoTask.getData();
      //  } catch (InterruptedException | ExecutionException e) {
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new ServiceException(e.getMessage());
//        }
        //业务数据录入
        //资产表
        //List<AmsAssetInfo> assetInfos = new ArrayList<>();
        //资产所有者表
        //List<AmsOwnAsset> ownAssets = new ArrayList<>();
        //资产维护商维护资产表
        List<AsmsMaintenanceAsset> maintenanceAssets = new ArrayList<>();
        //资产维护商维护资产所有者方表
        List<AsmsOwnMaintenanceDept> asmsOwnMaintenanceDepts = new ArrayList<>();
        //资产维护商维护资产所有者方表
        List<AsmsOwnAddressAssetCode> codeList = new ArrayList<>();
        Set<String> codes =new HashSet<>();
        //中间表
        List<AsmsAssetFullInfo> fullInfos = new ArrayList<>();
        //资产基础数据录入
        List<SaveAmsAssetInfoBatchVo> amsAssetInfoBatchVos = new ArrayList<>();

        for (AssetFullInfoImportVo vo : list) {
            AmsAssetType type = typeMap.get(vo.getAssetTypeName());
            AmsAssetTemplate template = importAssetInfoVo.getTemplateNames().get(vo.getAssetTemplateName());
            AmsAssetBrand brand = importAssetInfoVo.getBrandNames().get(vo.getBrandName());
            AmsAssetProject project = importAssetInfoVo.getProjectNames().get(vo.getProjectName());
            //资产表
            AmsAssetInfo assetInfo = new AmsAssetInfo();
            assetInfo.setSn(vo.getSn());
            assetInfo.setAssetCode(vo.getSn());
            assetInfo.setAssetTemplateId(template.getAssetTemplateId());
            assetInfo.setBrandId(brand == null ? null : brand.getBrandId());
            assetInfo.setProjectId(project == null ? null : project.getProjectId());
            assetInfo.setCreateBy(SecurityUtils.getUsername());
            assetInfo.setCreateTime(System.currentTimeMillis());
            //资产所有者表
            AmsOwnAsset ownAsset = new AmsOwnAsset();
            AmsOwnAddress ownAddress = addressVoMap.get(vo.getFullAddress());
            ownAsset.setAddressId(ownAddress == null ? 0L : ownAddress.getAddressId());
            SysUser user = importDeptUserInfoVo.getUsers().get(vo.getPhonenumber());
            SysDept oDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getODeptShortName())), SysDept.class);
            ownAsset.setOwnDeptId(oDept.getDeptId());
            ownAsset.setOwnDeptAncestors(oDept.getAncestors());
            SysDept uDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getUDeptShortName())), SysDept.class);
            if(user!=null){
                ownAsset.setUserId(user.getUserId());
            }
            ownAsset.setUseDeptId(uDept.getDeptId());

            ownAsset.setCreateBy(SecurityUtils.getUsername());
            ownAsset.setCreateTime(System.currentTimeMillis());
            SaveAmsAssetInfoBatchVo saveAmsAssetInfoBatchVo = new SaveAmsAssetInfoBatchVo();
            saveAmsAssetInfoBatchVo.setAssetInfo(assetInfo);
            saveAmsAssetInfoBatchVo.setOwnAsset(ownAsset);
            saveAmsAssetInfoBatchVo.setIndex(vo.getIndex());
            amsAssetInfoBatchVos.add(saveAmsAssetInfoBatchVo);

        }
        R<Map<Integer, AssetInfoView>> saveAmsAssetInfoBatch = assetInfoController.saveAmsAssetInfoBatch(amsAssetInfoBatchVos);
        if (R.FAIL == saveAmsAssetInfoBatch.getCode()) {
            throw new ServiceException(saveAmsAssetInfoBatch.getMsg());
        }

        Map<Integer, AssetInfoView> assetInfoViewMap = saveAmsAssetInfoBatch.getData();
        for (AssetFullInfoImportVo vo : list) {
            SysDept oDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getODeptShortName())), SysDept.class);

            AmsOwnAddress ownAddress = addressVoMap.get(vo.getFullAddress());
            AssetInfoView assetInfoView = assetInfoViewMap.get(vo.getIndex());

            //资产维护商维护资产表
            AsmsMaintenanceAsset maintenanceAsset = new AsmsMaintenanceAsset();
            maintenanceAsset.setAssetId(assetInfoView.getAssetId());
            maintenanceAsset.setBindUserId(SecurityUtils.getUserId());
            SysDept mDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getMDeptShortName())), SysDept.class);
            maintenanceAsset.setMaintenanceDeptId(mDept.getDeptId());
            maintenanceAsset.setStartUseTime(vo.getStartUseTime());
            maintenanceAsset.setEndUseTime(vo.getEndUseTime());
            maintenanceAsset.setCreateBy(SecurityUtils.getUsername());
            maintenanceAsset.setCreateTime(System.currentTimeMillis());

            maintenanceAssets.add(maintenanceAsset);
            //资产维护商维护资产所有者方表
            AsmsOwnMaintenanceDept asmsOwnMaintenanceDept = new AsmsOwnMaintenanceDept();
            asmsOwnMaintenanceDept.setOwnDeptId(oDept.getDeptId());
            asmsOwnMaintenanceDept.setMaintenanceDeptId(mDept.getDeptId());
            asmsOwnMaintenanceDept.setCreateBy(SecurityUtils.getUsername());
            asmsOwnMaintenanceDept.setCreateTime(System.currentTimeMillis());

            asmsOwnMaintenanceDepts.add(asmsOwnMaintenanceDept);
            //位置码表
            if(StringUtils.isNotEmpty(vo.getAddressCode())){
                if(!codes.contains(vo.getAddressCode())){
                    try {
                        Map<String, AsmsOwnAddressAssetCode> map = addressCodesCheckTask.get();
                        if(!map.containsKey(vo.getAddressCode())){
                            AsmsOwnAddressAssetCode codeInfo =new AsmsOwnAddressAssetCode();
                            codeInfo.setCode(vo.getAddressCode());
                            codeInfo.setAddressId(ownAddress != null ? ownAddress.getAddressId() : 0L);
                            codeInfo.setDeptId(oDept.getDeptId());
                            codeInfo.setCreateBy(SecurityUtils.getUsername());
                            codeInfo.setCreateTime(System.currentTimeMillis());
                            codeList.add(codeInfo);
                        }
                    }catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                    codes.add(vo.getAddressCode());
                }
            }
        }
        asmsOwnAddressAssetCodeService.saveBatch(codeList);
        //正式录入，后期需要添加事务
        //资产维护商维护资产表
        asmsMaintenanceAssetService.saveBatch(maintenanceAssets);
        //资产维护商维护资产所有者方表
        Set<String> omIds =new HashSet<>();
        CompletableFuture<Boolean> moSaveTask = CompletableFuture.supplyAsync(() -> {
            // Set<AsmsOwnMaintenanceDept> needSaveList =new HashSet<>();
            for (AsmsOwnMaintenanceDept asmsOwnMaintenanceDept : asmsOwnMaintenanceDepts) {
                if(!omIds.contains(asmsOwnMaintenanceDept.getMaintenanceDeptId()+"_"+asmsOwnMaintenanceDept.getOwnDeptId())){
                    AsmsOwnMaintenanceDept one = asmsOwnMaintenanceDeptService.getOne(new QueryWrapper<AsmsOwnMaintenanceDept>()
                            .eq(AsmsOwnMaintenanceDept.MAINTENANCE_DEPT_ID, asmsOwnMaintenanceDept.getMaintenanceDeptId())
                            .eq(AsmsOwnMaintenanceDept.OWN_DEPT_ID, asmsOwnMaintenanceDept.getOwnDeptId()), false);
                    if(one==null){
                        // needSaveList.add(asmsOwnMaintenanceDept);
                        asmsOwnMaintenanceDeptService.save(asmsOwnMaintenanceDept);
                    }
                    omIds.add(asmsOwnMaintenanceDept.getMaintenanceDeptId()+"_"+asmsOwnMaintenanceDept.getOwnDeptId());
                }

            }
            return true;
        });
        try {
            moSaveTask.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("出错！");
        }
        for (AssetFullInfoImportVo vo : list) {
            AssetInfoView assetInfoView = assetInfoViewMap.get(vo.getIndex());
            SysUser user = importDeptUserInfoVo.getUsers().get(vo.getPhonenumber());
            SysDept uDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getUDeptShortName())), SysDept.class);
            SysDept oDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getODeptShortName())), SysDept.class);
            SysDept mDept = JSONObject.parseObject(JSONObject.toJSONString(deptMap.get(vo.getMDeptShortName())), SysDept.class);
            //中间表
            AsmsAssetFullInfo fullInfo = new AsmsAssetFullInfo();
            BeanUtils.copyProperties(vo, fullInfo);
            AtomicReference<AsmsMaintenanceAsset> maintenanceAsset = new AtomicReference<>(new AsmsMaintenanceAsset());
            maintenanceAssets.stream().anyMatch(item->{
                boolean isFind =false;
                if(item.getAssetId().equals(assetInfoView.getAssetId())){
                    maintenanceAsset.set(item);
                    isFind= true;
                }
                return isFind;
            });
            AtomicReference<AsmsOwnMaintenanceDept> asmsOwnMaintenanceDept = new AtomicReference<>(new AsmsOwnMaintenanceDept());
            asmsOwnMaintenanceDepts.stream().filter(item->{
                boolean isFind =false;
                if(item.getMaintenanceDeptId().equals(mDept.getDeptId())&&item.getOwnDeptId().equals(oDept.getDeptId())){
                    asmsOwnMaintenanceDept.set(item);
                    isFind= true;
                }
                return isFind;
            }).findAny();
            BeanUtils.copyProperties(maintenanceAsset.get(), fullInfo);
            BeanUtils.copyProperties(asmsOwnMaintenanceDept.get(), fullInfo);
            if(user!=null){
                BeanUtils.copyProperties(user, fullInfo);
            }

            BeanUtils.copyProperties(assetInfoView, fullInfo);
            fullInfo.setUAncestors(uDept.getAncestors());
            fullInfo.setUParentId(uDept.getParentId());
            fullInfo.setUDeptFullName(uDept.getDeptFullName());
            fullInfo.setUEmail(uDept.getEmail());
            fullInfo.setULeader(uDept.getLeader());
            fullInfo.setUPhone(uDept.getPhone());
            fullInfo.setOwnDeptId(oDept.getDeptId());
            fullInfo.setOwnDeptName(oDept.getDeptShortName());
            fullInfo.setMAncestors(mDept.getAncestors());
            fullInfo.setMParentId(mDept.getParentId());
            fullInfo.setMDeptFullName(mDept.getDeptFullName());
            fullInfo.setMEmail(mDept.getEmail());
            fullInfo.setMLeader(mDept.getLeader());
            fullInfo.setMPhone(mDept.getPhone());
            fullInfo.setBindTime(System.currentTimeMillis());
            fullInfo.setBindUserName(SecurityUtils.getUsername());
            fullInfos.add(fullInfo);
        }
        //中间表
        asmsAssetFullInfoService.saveBatch(fullInfos);
        return AjaxResult.success();
    }

    /**
     * 在返回分页数据的接口中处理远程调用错误
     * @return 错误信息
     */
    public TableDataInfo resovleError() {
        TableDataInfo info = new TableDataInfo();
        info.setMsg("系统异常，请联系管理员");
        info.setCode(500);
        info.setSuccess(false);
        return info;
    }

    /**
     * 获取今天开始的时间，如2022-06-08 00:00:00
     * @return 今天凌晨0点的时间戳（ms）
     */
    public Long getTodayStartTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取本周的开始时间，如2022-06-01 00:00:00
     * @return 本周周一凌晨0点的时间戳（ms）
     */
    public Long getThisWeekStartTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取本月的开始时间，如2022-06-01 00:00:00
     * @return 本月第一天凌晨0点的时间戳（ms）
     */
    public Long getThisMonthStartTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 获取今年的开始时间，如2022-01-01 00:00:00
     * @return 今年第一天凌晨0点的时间戳（ms）
     */
    public Long getThisYearStartTime() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.DAY_OF_YEAR, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTimeInMillis();
    }

    /**
     * 输入一个过去的时间，返回该时间与此刻时间的距离
     * @param pastTime 过去的某个时间 单位：毫秒
     * @return 几秒前、几小时前等
     */
    public String getPastTimeLength(Long pastTime) {
        long SECOND = 1000L;
        long MINUTE = 60 * SECOND;
        long HOUR = 60 * MINUTE;
        long DAY = 24 * HOUR;

        String result;
        long timeDiff = System.currentTimeMillis() - pastTime;
        if (timeDiff <= 0L) {
            throw new ServiceException("input time is invalid!");

        } else if (timeDiff >= SECOND && timeDiff < MINUTE) {
            result = "刚刚";
            return result;

        } else if (timeDiff >= MINUTE && timeDiff < HOUR) {
            result = (timeDiff / MINUTE) + "分钟前";
            return result;

        } else if (timeDiff >= HOUR && timeDiff < DAY) {
            result = (timeDiff / HOUR) + "小时前";
            return result;

        } else {
            result = (timeDiff / DAY) + "天前";
            return result;
        }
    }

    /**
     * 保留两位小数的除法
     * @param a 被除数
     * @param b 除数
     * @return 结果字符串
     */
    public String keepTwoDecimalDiv(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("the divide number can't be zero!");
        }
        DecimalFormat format = new DecimalFormat("0.00");
        return format.format( (a * 1.0) / b);
    }

    /**
     * 获取已经取消的故障
     * @return
     */
    public Set<Long> getHasCancelFaults() {
        List<AsmsFaultReportStage> reportStages = asmsFaultReportStageService
                .list(new QueryWrapper<AsmsFaultReportStage>().eq(AsmsFaultReportStage.IS_CANCEL, 0));
        return reportStages.stream().map(AsmsFaultReportStage::getFaultAssetId).collect(Collectors.toSet());
    }

}